package org.dawfinn.droiditarian.server;

import java.text.DateFormat;
import java.util.Date;
import java.util.List;

import javax.jdo.PersistenceManager;
import javax.jdo.Query;
import javax.jdo.Transaction;

import org.dawfinn.droiditarian.client.admin.ClientDeed;
import org.dawfinn.droiditarian.client.admin.DeedsService;
import org.dawfinn.droiditarian.server.data.Deed;
import org.dawfinn.droiditarian.server.data.PMF;
import org.dawfinn.droiditarian.server.data.User;

import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.datastore.Link;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;

@SuppressWarnings("serial")
public class DeedsServiceImpl extends RemoteServiceServlet implements DeedsService {

	private static final DateFormat formatter = DateFormat.getInstance();

	public ClientDeed createDeed(String name, String description, String explanation, String moreInfo, String releaseDate, String sessionId) {
		verifySessionId(sessionId);
		try {
			Date parsedReleaseDate = formatter.parse(releaseDate);
			PersistenceManager pm = PMF.get().getPersistenceManager();
			Deed result = pm.makePersistent(new Deed(name, description, explanation, new Link(moreInfo), parsedReleaseDate));
			return toClientDeed(result);
		} catch (Exception ex) {
			return null;
		}
	}

	public boolean deleteDeed(String key, String sessionId) {
		verifySessionId(sessionId);
		PersistenceManager pm = PMF.get().getPersistenceManager();
		Deed d = pm.getObjectById(Deed.class, KeyFactory.stringToKey(key));
		pm.deletePersistent(d);

		return true;
	}

	public ClientDeed editDeed(String key, String name, String description, String explanation, String moreInfo, String releaseDate, String sessionId) {
		verifySessionId(sessionId);
		try {
			Date parsedReleaseDate = formatter.parse(releaseDate);
			PersistenceManager pm = PMF.get().getPersistenceManager();
			Deed d = pm.getObjectById(Deed.class, KeyFactory.stringToKey(key));
			Transaction tx = pm.currentTransaction();
			tx.begin();
			d.setName(name);
			d.setDescription(description);
			d.setExplanation(explanation);
			d.setMoreInfo(new Link(moreInfo));
			d.setReleaseDate(parsedReleaseDate);
			tx.commit();
			return toClientDeed(d);
		} catch (Exception ex) {
			return null;
		}
	}

	@SuppressWarnings("unchecked")
	public ClientDeed[] getDeeds(String sessionId) {
		verifySessionId(sessionId);
		PersistenceManager pm = PMF.get().getPersistenceManager();

		List<Deed> deeds = ((List<Deed>) pm.newQuery(Deed.class).execute());
		ClientDeed[] result = new ClientDeed[deeds.size()];
		int i = 0;
		for (Deed d : deeds) {
			result[i++] = toClientDeed(d);
		}
		return result;
	}

	@SuppressWarnings("unchecked")
    private void verifySessionId(String sessionId) {
		PersistenceManager pm = PMF.get().getPersistenceManager();
		Query q = pm.newQuery(User.class);
		q.declareParameters("String sessionId");
		q.setFilter("currentSid == sessionId");
		List<User> result = (List<User>) q.execute(sessionId);
		if (result.size() < 1)
			throw new LoginException(); 
	}

	static class LoginException extends RuntimeException {
	}

	private ClientDeed toClientDeed(Deed d) {
		return new ClientDeed(d.getWebsafeKey(), d.getName(), d.getDescription(), d.getExplanation(), d.getMoreInfo().getValue(), formatter.format(d
		        .getReleaseDate()), d.getFavoriteCount(), d.getCompletedCount());
	}
}
